package com.smcaiot.filesync.starter.app;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.smcaiot.filesync.starter.constants.HandlerType;
import com.smcaiot.filesync.starter.service.FileSyncService;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.annotation.PostConstruct;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static com.smcaiot.filesync.starter.constants.Constants.YES;

@ConfigurationProperties(prefix = FileSyncProperties.PREFIX)
@Data
@Slf4j
public class FileSyncProperties {

    @Autowired
    private FileSyncService fileSyncService;

    @PostConstruct
    public void init() {
        schedules.add(getCompress().setRunnable(fileSyncService::compressFiles));
        schedules.add(getPush().setRunnable(fileSyncService::push));
        schedules.add(getPull().setRunnable(fileSyncService::pull));
        List<Entity> scheduleInfos = findScheduleInfos();
        if (CollUtil.isEmpty(scheduleInfos)) {
            return;
        }
        scheduleInfos.forEach(schedule -> {
            String scheduleType = schedule.getStr("schedule_type");
            switch (HandlerType.valueOf(scheduleType)) {
                case compress:
                    addSchedule(getCompress(), schedule);
                    break;
                case push:
                    addSchedule(getPush(), schedule);
                    break;
                case pull:
                    addSchedule(getPull(), schedule);
                    break;
                default:
                    throw new RuntimeException("不支持的任务类型：" + scheduleType);
            }
        });
    }

    private void addSchedule(Schedule task, Entity schedule) {
        if (task.getOpen()) {
            return;
        }
        task.setId(schedule.getInt("id"));
        updateSchedule(task, schedule);
    }

    public void updateSchedule(Schedule task, Entity schedule){
        task.setOpen(YES.equals(schedule.getStr("schedule_open")));
        task.setCron(schedule.getStr("schedule_cron"));
        task.setName(schedule.getStr("schedule_name"));
        task.setType(schedule.getStr("schedule_type"));
    }

    private List<Entity> findScheduleInfos() {
        try {
            return Db.use().query("select * from schedule_info where schedule_type in ('compress', 'pull', 'push')");
        } catch (Exception e) {
            log.warn("查询数据库定时任务配置失败：{}", e.getMessage());
            return new ArrayList<>();
        }
    }

    public static final String PREFIX = "filesync";

    /**
     * 文件默认上传目录
     */
    private String baseDir;

    /**
     * 当前starter所在的服务，RemoteController接口的统一前缀
     */
    private String apiPrefix;

    /**
     * 定时任务是否并行
     */
    private Boolean parallel;

    private Compress compress = new Compress();

    private Push push = new Push();

    private Pull pull = new Pull();

    private List<Schedule> schedules = new ArrayList<>();

    @Data
    @Accessors(chain = true)
    public static class Compress extends Schedule {
        private String name = HandlerType.compress.getName();
        private String type = HandlerType.compress.name();
        /**
         * 压缩文件最大限制，单位（kb）
         */
        private long maxSize;

        /**
         * 图片压缩比例
         */
        private double scale;
    }

    @Data
    @Accessors(chain = true)
    public static class Push extends Schedule {
        private String name = HandlerType.push.getName();
        private String type = HandlerType.push.name();
        /**
         * 对接服务域名
         */
        private String remoteHost;
    }

    @Data
    @Accessors(chain = true)
    public static class Pull extends Schedule {
        private String name = HandlerType.pull.getName();
        private String type = HandlerType.pull.name();
        /**
         * 对接服务域名
         */
        private String remoteHost;
    }

    @Data
    @Accessors(chain = true)
    public static class Schedule {
        private Integer id;
        private String name;
        private String type;
        /**
         * 是否打开拉取文件定时任务
         */
        private Boolean open = false;

        /**
         * 拉取文件定时任务cron
         */
        private String cron;
        private Runnable runnable;
    }

}
